/*
 * EventTimeResource.cpp
 *
 *  Created on: 2013. 9. 9.
 *      Author: mega@gamevil.com
 */

#include "../User.h"
#include "../NUtil/Utils.h"
#include "../NLogic/Space.h"
#include "../NResource/Static.h"
#include "EventTimeResource.h"

namespace ProjectZ { namespace NResource {

EventTimeResource::EventTimeResource()
{
	pEventTimeAD	= new EventTimeData;
	pEventTimeIOS	= new EventTimeData;

	_count = 0;
}

EventTimeResource::~EventTimeResource()
{
	delete pEventTimeAD;
	delete pEventTimeIOS;
}

bool EventTimeResource::LoadResource()
{
	if (false == pEventTimeAD->LoadResource(MARKET_GOOGLE, SC_KAKAO_GOOGLE))
		return false;

	if (false == pEventTimeIOS->LoadResource(MARKET_IOS, SC_KAKAO_IOS))
		return false;

	return true;
}

EventTimeData::Flyweight * EventTimeResource::GetFly(User * pUser, int nType)
{
	NUtil::MarketType marketType = NUtil::GetMarketType(pUser->GetCompany(), pUser->GetSaleCode());

	switch (marketType)
	{
	case NUtil::MarketType::AD_KAKAO:
		return pEventTimeAD->GetFly(nType);

	case NUtil::MarketType::IOS_KAKAO:
		return pEventTimeIOS->GetFly(nType);

	default:
		return NULL;
	}

	return NULL;
}


EventTimeData::~EventTimeData()
{
	std::for_each(clsMap.begin(), clsMap.end(), [&](DATATREE::value_type & pair) {
		std::for_each(pair.second.begin(), pair.second.end(), [&](Flyweight * pFly) {
			delete pFly;
		});
	});
}

void
EventTimeData::Clear()
{
	std::for_each(clsMap.begin(), clsMap.end(), [&](DATATREE::value_type & pair) {
		std::for_each(pair.second.begin(), pair.second.end(), [&](Flyweight * pFly) {
			delete pFly;
		});
		pair.second.clear();
	});
	clsMap.clear();
}


bool EventTimeData::LoadResource(int company, int saleCode)
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::SELECT);
	clsAuto->MakeQuery("SELECT NATIONAL_CODE, type, sub_type, UNIX_TIMESTAMP(start_date), UNIX_TIMESTAMP(end_date) "
			"FROM resource_event_time WHERE company=%d AND sale_cd=%d", company, saleCode);

	if (false == ::Database::GETSESSION()->SyncExecute(1, clsAuto))
		return false;

	if( clsAuto->GetErrorIdx() != 0 )
		return false;

	if (0 == clsAuto->ResultRowCount())
		return false;

	Clear();

	while( clsAuto->Next() )
	{
		::Toolkit::Str<3> NATIONAL_CODE;
		EventTimeData::Flyweight * pFly = new EventTimeData::Flyweight;

		clsAuto->GetRecord() >> NATIONAL_CODE >> pFly->_TYPE >> pFly->_SUB_TYPE >> pFly->_START_SEC >> pFly->_END_SEC;

		if (0 != Config::Instance().GetResourceDatabase()._strNational.compare(NATIONAL_CODE.c_str()))
		{
			DEBUGLOG("%s:%d NATIONAL_CODE ERROR!!! Config National Code [%s] , Resource National Code [%s]",
					__FILE__, __LINE__,
					Config::Instance().GetResourceDatabase()._strNational.c_str(),
					NATIONAL_CODE.c_str());
			return false;
		}

		clsMap[pFly->_TYPE].push_back(pFly);
	}

	DEBUGLOG("company=%d, sale_code=%d ------------------------", company, saleCode);
	std::for_each(clsMap.begin(), clsMap.end(), [&](DATATREE::value_type & pair) {
		std::for_each(pair.second.begin(), pair.second.end(), [&](Flyweight * pFly) {
			DEBUGLOG("type=%d, subtype=%d, start=%ld, end=%ld", pair.first, pFly->_SUB_TYPE, pFly->_START_SEC, pFly->_END_SEC);
		});
	});
	DEBUGLOG("-------------------------------------------------");


	return true;
}

EventTimeData::Flyweight * EventTimeData::GetFly(int nType)
{
	auto mIter = clsMap.find(nType);

	if (mIter == clsMap.end())
		return NULL;

	time_t curTime = time(NULL);

	DATAVECTOR & clsVector = mIter->second;
	auto vIter = clsVector.begin();
	for (; vIter != clsVector.end(); ++vIter)
	{
		Flyweight * pFly = (* vIter);

		TESTLOG("%s : type=%d, start=%ld, end=%ld, current=%ld", __FUNCTION__, nType, pFly->_START_SEC, pFly->_END_SEC, curTime);

		if (pFly->_START_SEC <= curTime && curTime <= pFly->_END_SEC)
		{
			return pFly;
		}
	}

	return NULL;
}

int
EventTimeResource::EventDungeonRemainMinute(User * pUser)
{
	/*
	 * 이벤트 던전 오픈 남은 시간 계산
	 */
	time_t curSec = time(NULL);

	EventTimeData::Flyweight * pFly = GetFly(pUser, static_cast<int>(EM_EVENT_TYPE_EVENT_DUNGEON_OPEN));
	if (NULL == pFly)
	{
		return 0;
	}

	return (pFly->_END_SEC - curSec) / 60;
}

bool
EventTimeResource::IsEvent(User * pUser, EventType eType)
{
	/*
	 * 이벤트 여부 판단
	 */

	int nType = static_cast<int>(eType);

	EventTimeData::Flyweight * pFly = GetFly(pUser, nType);
	if (NULL == pFly)
	{
		return false;
	}

	return true;
}

bool
EventTimeResource::IsDungeonReward(User * pUser)
{
	/*
	 * 이벤트 기간인 경우 특정 던전이 이벤트 적용 대상인지 결정
	 */

	NLogic::Space * pSpace = pUser->GetSpace();
	if (NULL == pSpace)
	{
		return false;
	}

	// 마을에서 아이템 뽑기를 한 경우는 던전 여부는 판단하지 않는다
	if (pSpace->GetData()._spaceType == NLogic::Space::SpaceType::WORLD)
	{
		return true;
	}

	bool bEvent = false;

	if (true == pSpace->IsDungeon())
	{
		NResource::DungeonRewardData::Key clsKey(NResource::DungeonRewardResource::DungeonRewardType::EM_DUNGEON_REWARD_EVENT, pUser->GetSpace()->GetData()._table_id);

		NResource::DungeonRewardData::Flyweight * pFly =
				NResource::Static::InstancePtr()->GetDungeonReward()->GetFly(pUser, clsKey);

		if (NULL == pFly)
			return false;

		// 이벤트 적용 대상 던전 여부 확인
		if (1 == pFly->_VALUE1)
		{
			bEvent = true;
		}
	}

	return bEvent;
}

bool
EventTimeResource::IsOpenEventDungeon(User * pUser)
{
	return IsEvent(pUser, EM_EVENT_TYPE_EVENT_DUNGEON_OPEN);
}

bool
EventTimeResource::IsDungeonRewardZenCardEvent(User * pUser)
{
	/*
	 * 젠 카드 가격 할인 이벤트
	 */
	bool bEvent = IsEvent(pUser, EM_EVENT_TYPE_DUNGEON_REWARD_ZEN);

	// 던전 보상인 경우 던전의 이벤트 적용 여부 확인
	if (true == bEvent)
	{
		bEvent = IsDungeonReward(pUser);
	}

	return bEvent;
}

bool
EventTimeResource::IsDungeonRewardItemGradeEvent(User * pUser)
{
	/*
	 * 던전 보상 품질 결정 확률 이벤트
	 */
	bool bEvent = IsEvent(pUser, EM_EVENT_TYPE_DUNGEON_REWARD_GRADE);

	// 던전 보상인 경우 던전의 이벤트 적용 여부 확인
	if (true == bEvent)
	{
		bEvent = IsDungeonReward(pUser);
	}

	return bEvent;
}

bool
EventTimeResource::IsDungeonRewardItemQualityEvent(User * pUser)
{
	/*
	 * 던전 보상 아이템 등급 결정 확률 이벤트
	 */
	bool bEvent = IsEvent(pUser, EM_EVENT_TYPE_DUNGEON_REWARD_QUALITY);

	// 던전 보상인 경우 던전의 이벤트 적용 여부 확인
	if (true == bEvent)
	{
		bEvent = IsDungeonReward(pUser);
	}

	return bEvent;
}

bool
EventTimeResource::IsDungeonRewardItemRefineEvent(User * pUser)
{
	/*
	 * 던전 보상 아이템 제련 단계 결정 확률 이벤트
	 */
	bool bEvent = IsEvent(pUser, EM_EVENT_TYPE_DUNGEON_REWARD_REFINE);

	// 던전 보상인 경우 던전의 이벤트 적용 여부 확인
	if (true == bEvent)
	{
		bEvent = IsDungeonReward(pUser);
	}

	return bEvent;
}

bool
EventTimeResource::IsItemRefineEvent(User * pUser)
{
	/*
	 * 아이템 제련 성공 확률 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_ITEM_REFINE);
}

bool
EventTimeResource::IsDungeonDayEvent(User * pUser)
{
	/*
	 * 던전 요일별 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_DUNGEON_DAILY_EVENT);
}

bool
EventTimeResource::IsFairyGachyaEvent(User * pUser)
{
	/*
	 * 페어리 뽑기 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_FAIRY_GACHYA);
}

bool
EventTimeResource::IsBattlePetGachyaEvent(User * pUser)
{
	/*
	 * 전투펫 뽑기 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_BATTLEPET_GACHYA);
}

bool
EventTimeResource::IsDailyAttendEvent(User * pUser)
{
	/*
	 * 일일 출석 보상 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_DAILY_ATTEND);
}

bool
EventTimeResource::IsSocialActionRewardEvent(User * pUser)
{
	/*
	 * 소셜 액션 보상 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_SOCIAL_ACTION_REWARD);
}

bool
EventTimeResource::IsFriendInviteMeetEvent(User * pUser)
{
	/*
	 * 친구 초대 번개 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_FRIEND_INVITE_MEET);
}

bool
EventTimeResource::IsZENDiscountEvent(User * pUser)
{
	/*
	 * 젠 상품 할인 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_ZEN_DISCOUNT);
}

bool
EventTimeResource::IsLaunchingEvent(User * pUser)
{
	/*
	 * 론칭 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_LAUNCHING_EVENT);
}

bool
EventTimeResource::IsConnectEvent(User  * pUser)
{
	/*
	 * 접속 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_CONNECT_EVENT);
}

bool
EventTimeResource::IsWorldBossEvent(User * pUser)
{
//	bool bRet = false;
//	// subType 은 6으로 일단 fix : 김수환
//	for (int i = 0; i < 6; i++)
//	{
//		EventTimeData::Key clsKey(EM_EVENT_TYPE_WORLDBOSS_EVENT, i);
//		bRet = IsEvent(pUser, clsKey);
//
//		if (true == bRet)
//		{
//			subType = i;
//			return true;
//		}
//	}
////	EventTimeData::Key clsKey(EM_EVENT_TYPE_WORLDBOSS_EVENT, 0);
////	return IsEvent(pUser, clsKey);
//
//	subType = 0;
//	return bRet;

	return IsEvent(pUser, EM_EVENT_TYPE_WORLDBOSS_EVENT);
}

bool
EventTimeResource::IsWorldBossReward(User * pUser)
{
	return IsEvent(pUser, EM_EVENT_TYPE_WORLDBOSS_REWARD);
}

bool
EventTimeResource::IsStaminaRecoveryTimeEvent(User * pUser)
{
	/*
	 * 이벤트 던전 스태미너 복구 시간 감소 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_STAMINA_EVENT);
}

int
EventTimeResource::WorldBossEventRemainMinute(User * pUser)
{
	/*
	 * 이벤트 던전 오픈 남은 시간 계산
	 */
	time_t curSec = time(NULL);

	EventTimeData::Flyweight * pFly = GetFly(pUser, static_cast<int>(EM_EVENT_TYPE_WORLDBOSS_EVENT));

	if (NULL == pFly)
	{
		return 0;
	}

	return (pFly->_END_SEC - curSec);
}

bool
EventTimeResource::IsPVPWorldRankingEvent(User * pUser)
{
	/*
	 * PVP 전국 랭킹 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_PVP_WORLD_RANKING);
}

bool
EventTimeResource::IsMagicRefineDestroyEvent(User * pUser)
{
	/*
	 * 마법 제련 실패 시 아이템 파괴 확률 이벤트
	 */
	return IsEvent(pUser, EM_EVENT_TYPE_MAGIG_REFINE_DESTROY);
}

} /* NResource */ } /* ProjectZ */
